[HVM][SVM] Modify the interrupt/event injection logic.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 20 Dec 2006 10:14:50 +0000 (10:14 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 20 Dec 2006 10:14:50 +0000 (10:14 +0000)
Resolves performance issues concerning AMD-V virtual interrupt/event
injection:
 - Remove extra VINTRs vmexits, and only setup fake interrupt if intr
   pending.
 - Allow both event injection and interrupt injection concurrently in
   vmcb.

Signed-off-by: Tom Woller <thomas.woller@amd.com>
xen/arch/x86/hvm/svm/intr.c
xen/arch/x86/hvm/svm/svm.c
xen/include/asm-x86/hvm/svm/vmcb.h

index e42438aadbfe33e8562959225ebce34147dafcf8..97447d9f64ace066a8fe524c111db64cf2fcdb0c 100644 (file)
@@ -78,26 +78,6 @@ asmlinkage void svm_intr_assist(void)
         re_injecting = 1;
     }
 
-    /*
-     * If event requires injecting then do not inject int.
-     */
-    if ( unlikely(v->arch.hvm_svm.inject_event) )
-    {
-        v->arch.hvm_svm.inject_event = 0;
-        return;
-    }
-
-    /*
-     * Create a 'fake' virtual interrupt on to intercept as soon
-     * as the guest _can_ take interrupts.
-     */
-    if ( irq_masked(vmcb->rflags) || vmcb->interrupt_shadow )
-    {
-        vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
-        svm_inject_extint(v, 0x0); /* actual vector doesn't really matter */
-        return;
-    }
-
     /* Previous interrupt still pending? */
     if ( vmcb->vintr.fields.irq )
     {
@@ -124,7 +104,20 @@ asmlinkage void svm_intr_assist(void)
         hvm_set_callback_irq_level();
 
         if ( cpu_has_pending_irq(v) )
+        {
+            /*
+             * Create a 'fake' virtual interrupt on to intercept as soon
+             * as the guest _can_ take interrupts.  Do not obtain the next
+             * interrupt from the vlapic/pic if unable to inject.
+             */
+            if ( irq_masked(vmcb->rflags) || vmcb->interrupt_shadow )  
+            {
+                vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
+                svm_inject_extint(v, 0x0); /* actual vector doesn't really matter */
+                return;
+            }
             intr_vector = cpu_get_interrupt(v, &intr_type);
+        }
     }
 
     /* have we got an interrupt to inject? */
index a5f39dacdf9447f31be70fd0f4e4257a2513126b..ebb1e4f614e6a2df72da25068c91df9e669ce7b4 100644 (file)
@@ -191,7 +191,6 @@ static inline void svm_inject_exception(struct vcpu *v, int trap,
     ASSERT(vmcb->eventinj.fields.v == 0);
     
     vmcb->eventinj = event;
-    v->arch.hvm_svm.inject_event=1;
 }
 
 static void stop_svm(void)
@@ -2564,8 +2563,6 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
     exit_reason = vmcb->exitcode;
     save_svm_cpu_user_regs(v, regs);
 
-    v->arch.hvm_svm.inject_event = 0;
-
     if (exit_reason == VMEXIT_INVALID)
     {
         svm_dump_vmcb(__func__, vmcb);
@@ -2933,7 +2930,7 @@ asmlinkage void svm_asid(void)
         clear_bit( ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags );
     }
 }
-
+  
 /*
  * Local variables:
  * mode: C
index 81d41ea68815767823001950dbd8ad098be00c64..3340ec3a9ee4b8c2fddc765982552b668835866b 100644 (file)
@@ -456,7 +456,6 @@ struct arch_svm_struct {
     u32                 *msrpm;
     u64                 vmexit_tsc; /* tsc read at #VMEXIT. for TSC_OFFSET */
     int                 saved_irq_vector;
-    u32                 inject_event;
     u32                 launch_core;
     u32                 asid_core;